#ifndef REMOTE_CLIENT_TUNNEL_SESSION_H_
#define REMOTE_CLIENT_TUNNEL_SESSION_H_

#include "vzbase/base/boostsettings.h"
#include "vzbase/base/loggingsettings.h"
#include "vzconn/conn/vzconnect.h"

namespace remote {

struct TunnelSettings {
  std::string   remote_name;
  std::string   local_name;
  std::string   des_addr;
  uint16        des_port;
  std::string   server_addr;
  uint16        server_port;
  std::string   bind_addr;
  uint16        bind_port;
};

typedef boost::shared_ptr<boost::asio::ip::tcp::socket> SocketPtr;

class TunnelClientSession : public boost::noncopyable,
  public boost::enable_shared_from_this < TunnelClientSession > {
 public:
  typedef boost::shared_ptr<TunnelClientSession> Ptr;

  TunnelClientSession(boost::asio::io_service &io_service,
                      TunnelSettings &tunnel_settings,
                      SocketPtr local_socket,
                      SocketPtr remote_socket);

  virtual ~TunnelClientSession();

  bool Start();
  void Stop();
 private:
  void HandleLocalRead(const boost::system::error_code& err,
                       int read_size);
  void HandleLocalWrite(const boost::system::error_code& err);

  //
  void HandleRemoteRead(const boost::system::error_code& err,
                        int read_size);
  void HandleRemoteWrite(const boost::system::error_code& err);
  void StartReadLocalData();
  void StartReadRemoteData();
  void CloseSession();
 private:
  static const uint32 DEFAULT_BUFFER_SIZE = 4096;
  boost::asio::io_service &io_service_;
  TunnelSettings tunnel_settings_;
  SocketPtr local_socket_;
  SocketPtr remote_socket_;
  char local_buffer_[DEFAULT_BUFFER_SIZE];
  char remote_buffer_[DEFAULT_BUFFER_SIZE];
};

}

#endif  // REMOTE_CLIENT_TUNNEL_SESSION_H_
